package com.sandyz.virtualcam.utils

import android.content.res.Resources
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Matrix
import androidx.annotation.DrawableRes

/**
 * 测试用
 *
 * 位图加载工具类
 * 
 * 主要功能：
 * 1. 从资源加载位图
 * 2. 按指定尺寸缩放位图
 * 3. 保持宽高比例缩放
 * 4. 内存优化处理
 * 
 * 实现细节：
 * - 使用BitmapFactory.Options进行预加载
 * - 支持inSampleSize采样率优化
 * - 使用Matrix进行精确缩放
 * - 提供多种缩放策略
 * 
 * @author sandyz987
 * @date 2023/11/18
 */
object BitmapLoader {
    /**
     * 1. 按指定宽高加载位图
     * 
     * 处理流程：
     * 1.1 参数检查
     * 1.2 预加载获取原始尺寸
     * 1.3 计算采样率
     * 1.4 加载并缩放位图
     * 
     * @param res 资源对象
     * @param resId 资源ID
     * @param decodeWidth 目标宽度
     * @param decodeHeight 目标高度
     * @return Bitmap? 加载的位图
     */
    fun decodeBitmapFromResource(
        res: Resources?,
        @DrawableRes resId: Int,
        decodeWidth: Int,
        decodeHeight: Int
    ): Bitmap? {
        // 1.1 参数检查
        if (resId == 0) {
            return null
        }
        if (decodeHeight <= 0 || decodeWidth <= 0) {
            return null
        }

        // 1.2 预加载获取原始尺寸
        val options = BitmapFactory.Options()
        options.inJustDecodeBounds = true
        BitmapFactory.decodeResource(res, resId, options)
        val imgWidth = options.outWidth
        val imgHeight = options.outHeight

        // 1.3 计算采样率
        var inSampleSize = 1
        if (imgWidth > decodeWidth || imgHeight > decodeHeight) {
            val halfWidth = imgWidth / 2
            val halfHeight = imgHeight / 2
            while (halfWidth / inSampleSize >= decodeWidth &&
                halfHeight / inSampleSize >= decodeHeight
            ) {
                inSampleSize *= 2
            }
        }

        // 1.4 加载并缩放位图
        options.inJustDecodeBounds = false
        options.inSampleSize = inSampleSize
        val bitmap = BitmapFactory.decodeResource(res, resId, options) ?: return null
        val matrix = Matrix().apply {
            postScale((decodeWidth / bitmap.width.toFloat()), (decodeHeight / bitmap.height.toFloat()))
        }
        return Bitmap.createBitmap(bitmap, 0, 0, bitmap.width, bitmap.height, matrix, true)
    }

    /**
     * 2. 按指定宽度加载位图（保持宽高比）
     * 
     * 处理流程：
     * 2.1 参数检查
     * 2.2 预加载获取原始尺寸
     * 2.3 计算目标高度
     * 2.4 计算采样率
     * 2.5 加载并缩放位图
     * 
     * @param res 资源对象
     * @param resId 资源ID
     * @param decodeWidth 目标宽度
     * @return Bitmap? 加载的位图
     */
    fun decodeBitmapFromResourceByWidth(
        res: Resources?,
        @DrawableRes resId: Int,
        decodeWidth: Int
    ): Bitmap? {
        // 2.1 参数检查
        if (resId == 0) {
            return null
        }
        if (decodeWidth <= 0) {
            return null
        }

        // 2.2 预加载获取原始尺寸
        val options = BitmapFactory.Options()
        options.inJustDecodeBounds = true
        BitmapFactory.decodeResource(res, resId, options)
        val imgWidth = options.outWidth
        val imgHeight = options.outHeight

        // 2.3 计算目标高度
        val heightDivWidth = imgHeight / imgWidth.toFloat()
        val decodeHeight = decodeWidth * heightDivWidth

        // 2.4 计算采样率
        var inSampleSize = 1
        if (imgWidth > decodeWidth || imgHeight > decodeHeight) {
            val halfWidth = imgWidth / 2
            val halfHeight = imgHeight / 2
            while (halfWidth / inSampleSize >= decodeWidth &&
                halfHeight / inSampleSize >= decodeHeight
            ) {
                inSampleSize *= 2
            }
        }

        // 2.5 加载并缩放位图
        options.inJustDecodeBounds = false
        options.inSampleSize = inSampleSize
        val bitmap = BitmapFactory.decodeResource(res, resId, options) ?: return null
        val matrix = Matrix().apply {
            postScale((decodeWidth.toFloat() / bitmap.width), (decodeHeight / bitmap.height))
        }
        return Bitmap.createBitmap(bitmap, 0, 0, bitmap.width, bitmap.height, matrix, true)
    }

    /**
     * 3. 按指定高度加载位图（保持宽高比）
     * 
     * 处理流程：
     * 3.1 参数检查
     * 3.2 预加载获取原始尺寸
     * 3.3 计算目标宽度
     * 3.4 计算采样率
     * 3.5 加载并缩放位图
     * 
     * @param res 资源对象
     * @param resId 资源ID
     * @param decodeHeight 目标高度
     * @return Bitmap? 加载的位图
     */
    fun decodeBitmapFromResourceByHeight(
        res: Resources?,
        @DrawableRes resId: Int,
        decodeHeight: Int
    ): Bitmap? {
        // 3.1 参数检查
        if (resId == 0) {
            return null
        }
        if (decodeHeight <= 0) {
            return null
        }

        // 3.2 预加载获取原始尺寸
        val options = BitmapFactory.Options()
        options.inJustDecodeBounds = true
        BitmapFactory.decodeResource(res, resId, options)
        val imgWidth = options.outWidth
        val imgHeight = options.outHeight

        // 3.3 计算目标宽度
        val widthDivHeight = imgWidth / imgHeight.toFloat()
        val decodeWidth = decodeHeight * widthDivHeight

        // 3.4 计算采样率
        var inSampleSize = 1
        if (imgWidth > decodeWidth || imgHeight > decodeHeight) {
            val halfWidth = imgWidth / 2
            val halfHeight = imgHeight / 2
            while (halfWidth / inSampleSize >= decodeWidth &&
                halfHeight / inSampleSize >= decodeHeight
            ) {
                inSampleSize *= 2
            }
        }

        // 3.5 加载并缩放位图
        options.inJustDecodeBounds = false
        options.inSampleSize = inSampleSize
        val bitmap = BitmapFactory.decodeResource(res, resId, options) ?: return null
        val matrix = Matrix().apply {
            postScale((decodeWidth / bitmap.width), (decodeHeight / bitmap.height.toFloat()))
        }
        return Bitmap.createBitmap(bitmap, 0, 0, bitmap.width, bitmap.height, matrix, true)
    }

    /**
     * 4. 缩放已有位图
     * 
     * 处理流程：
     * 4.1 参数检查
     * 4.2 创建缩放矩阵
     * 4.3 执行缩放
     * 
     * @param bitmapSrc 源位图
     * @param targetWidth 目标宽度
     * @param targetHeight 目标高度
     * @return Bitmap? 缩放后的位图
     */
    fun resizeBitmap(bitmapSrc: Bitmap?, targetWidth: Int, targetHeight: Int): Bitmap? {
        // 4.1 参数检查
        val bitmap = bitmapSrc ?: return null

        // 4.2 创建缩放矩阵
        val matrix = Matrix().apply {
            postScale((targetWidth / bitmap.width.toFloat()), (targetHeight / bitmap.height.toFloat()))
        }

        // 4.3 执行缩放
        return Bitmap.createBitmap(bitmap, 0, 0, bitmap.width, bitmap.height, matrix, true)
    }
}